package com.hzzc.core.service.sdk;

import com.hzzc.BizException;
import com.hzzc.Result;
import com.hzzc.api.*;
import com.hzzc.core.dao.SSOUserMapper;
import com.hzzc.core.model.ExpireSSOUser;
import com.hzzc.core.model.SSOUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.Iterator;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 用户服务
 * <p>
 * --用户登录服务
 * --用户登录验证服务
 */
@Service
public class ApiUserLoginService {

    /**
     * 登录用户数据过期期限:2小时
     */
    @Value("${login.expire:7200000}")
    private Long expireTime;

    @Autowired
    private SSOUserMapper ssoUserMapper;

    @Autowired
    private ApiAuthorityService apiAuthorityService;

    /**
     * token-userId
     */
    private Map<String, ExpireSSOUser> userLoginCode = new ConcurrentHashMap();

    /**
     * 将登录信息缓存起来
     *
     * @param code
     * @param ssoUser
     */
    private void addLoginCache(String code, SSOUser ssoUser) {
        userLoginCode.put(code, new ExpireSSOUser(ssoUser));
    }


    /**
     * 登录
     *
     * @param loginBean
     * @return
     * @throws BizException
     */

    public SSOLoginModel login(LoginBean loginBean) throws BizException {
        Example example = new Example(SSOUser.class);
        example.createCriteria().andEqualTo("account", loginBean.getAccount()).andEqualTo("pwd", loginBean.getPass());
        SSOUser ssoUser = ssoUserMapper.selectOneByExample(example);
        if (ssoUser == null) {
            throw new BizException("用户名或者密码错误！！");
        }
        if (ssoUser.getBlack()) {
            throw new BizException("限制登录！！");
        }
        clearLoginByBefore(ssoUser.getId());
        SSOLoginModel ssoLoginModel = new SSOLoginModel();
        ssoLoginModel.setCode(UUID.randomUUID().toString());
        ssoLoginModel.setTo(loginBean.getTo());
        addLoginCache(ssoLoginModel.getCode(), ssoUser);
        return ssoLoginModel;
    }

    /**
     * 删除
     *
     * @param id
     */
    private void clearLoginByBefore(Long id) {
        userLoginCode.remove(id);
    }


    public Result<String> checkAuthority(CheckBean checkBean) {
        if (StringUtils.isEmpty(checkBean.getCode())) {
            return Result.auth("expired", "无授权凭证");
        }
        ExpireSSOUser expireSSOUser = userLoginCode.get(checkBean.getCode());
        if (expireSSOUser == null || expireSSOUser.getSsoUser(expireTime) == null) {
            return Result.auth("expired", "登录过期，请重新登录");
        }
        expireSSOUser.setCreateTime(System.currentTimeMillis());

        SSOUser ssoUser = ssoUserMapper.selectByPrimaryKey(expireSSOUser.getSsoUser().getId());
        if (ssoUser.getBlack()) {
            return Result.error("限制登录！", "限制登录！");
        }
        if (apiAuthorityService.checkAuthority(checkBean.getApp(), expireSSOUser.getSsoUser().getId(), checkBean.getResource())) {
            return Result.success("权限校验成功", "ok");
        } else {
            return Result.reject("权限不足", "权限不足，请联系管理员");
        }
    }


    public Result<SSOApplicationUserAuthorityView> getUserApplicationUserAuthorityView(String appCode, String code) throws BizException {
        ExpireSSOUser expireSSOUser = userLoginCode.get(code);
        if (expireSSOUser == null || expireSSOUser.getSsoUser(expireTime) == null) {
            return Result.auth(null, "登录过期，请重新登录");
        }
        return Result.success(apiAuthorityService.getUserApplicationUserAuthorityView(appCode, expireSSOUser.getSsoUser().getId()), "");
    }

    public boolean logout(LogoutBean logoutBean) {
        ExpireSSOUser remove = userLoginCode.remove(logoutBean.getCode());
        return true;
    }

    @Scheduled(initialDelay = 1000L * 60 * 10, fixedDelay = 1000L * 60 * 30)
    public void checkExpire() {
        Iterator<Map.Entry<String, ExpireSSOUser>> iterator = userLoginCode.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, ExpireSSOUser> next = iterator.next();
            if (next.getValue().getSsoUser(expireTime) == null) {
                iterator.remove();
            }
        }
    }


}
